home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / tcsh / dist / sh.proc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-21  |  46.8 KB  |  1,988 lines

  1. /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.01/RCS/sh.proc.c,v 3.19 1991/11/26 04:28:26 christos Exp $ */
  2. /*
  3.  * sh.proc.c: Job manipulations
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "sh.h"
  38.  
  39. RCSID("$Id: sh.proc.c,v 3.19 1991/11/26 04:28:26 christos Exp $")
  40.  
  41. #include "ed.h"
  42. #include "tc.h"
  43. #include "tc.wait.h"
  44.  
  45. #if !defined(NSIG) && defined(SIGMAX)
  46. # define NSIG (SIGMAX+1)
  47. #endif /* !NSIG && SIGMAX */
  48. #if !defined(NSIG) && defined(_NSIG)
  49. # define NSIG _NSIG
  50. #endif /* !NSIG && _NSIG */
  51.  
  52. #ifdef aiws
  53. # undef HZ
  54. # define HZ 16
  55. #endif /* aiws */
  56.  
  57. #ifndef HZ
  58. # define HZ    100        /* for division into seconds */
  59. #endif
  60.  
  61. #if (defined(_BSD) && defined(_BSD_INCLUDES)) || (defined(IRIS4D) && __STDC__)
  62. # define BSDWAIT
  63. #endif
  64. #ifndef WTERMSIG
  65. # define WTERMSIG(w)    (((union wait *) &(w))->w_termsig)
  66. # ifndef BSDWAIT
  67. #  define BSDWAIT
  68. # endif
  69. #endif /* !WTERMSIG */
  70. #ifndef WEXITSTATUS
  71. # define WEXITSTATUS(w)    (((union wait *) &(w))->w_retcode)
  72. #endif /* !WEXITSTATUS */
  73. #ifndef WSTOPSIG
  74. # define WSTOPSIG(w)    (((union wait *) &(w))->w_stopsig)
  75. #endif /* WSTOPSIG */
  76.  
  77. #ifndef WCOREDUMP
  78. # ifdef BSDWAIT
  79. #  define WCOREDUMP(w)    (((union wait *) &(w))->w_coredump)
  80. # else /* !BSDWAIT */
  81. #  define WCOREDUMP(w)    ((w) & 0200)
  82. # endif /* !BSDWAIT */
  83. #endif /* !WCOREDUMP */
  84.  
  85. /*
  86.  * C Shell - functions that manage processes, handling hanging, termination
  87.  */
  88.  
  89. #define BIGINDEX    9    /* largest desirable job index */
  90.  
  91. #ifdef BSDTIMES
  92. # if defined(sun) || defined(hp9000)
  93. static struct rusage zru = {{0L, 0L}, {0L, 0L}, 0L, 0L, 0L, 0L,
  94.                 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L};
  95.  
  96. # else /* !sun && !hp9000 */
  97. #  ifdef masscomp
  98. /*
  99.  * Initialization of this structure under RTU 4.1A & RTU 5.0 is problematic
  100.  * because the first two elements are unions of a time_t and a struct timeval.
  101.  * So we'll just have to trust the loader to do the "right thing", DAS DEC-90.
  102.  */
  103. static struct rusage zru;
  104. #  else    /* masscomp */
  105. static struct rusage zru = {{0L, 0L}, {0L, 0L}, 0, 0, 0, 0, 0, 0, 0, 
  106.                 0, 0, 0, 0, 0, 0};
  107. #  endif /* masscomp */
  108. # endif    /* !sun && !hp9000 */
  109. #else /* ! BSDTIMES */
  110. # ifdef _SEQUENT_
  111. static struct process_stats zru = {{0L, 0L}, {0L, 0L}, 0, 0, 0, 0, 0, 0, 0,
  112.                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  113. # else /* !_SEQUENT_ */
  114. static struct tms zru = {0L, 0L, 0L, 0L}, lru = {0L, 0L, 0L, 0L};
  115. # endif    /* !_SEQUENT_ */
  116. #endif /* !BSDTIMES */
  117.  
  118. #ifndef RUSAGE_CHILDREN
  119. # define    RUSAGE_CHILDREN    -1
  120. #endif
  121.  
  122. static    void         pflushall    __P((void));
  123. static    void         pflush        __P((struct process *));
  124. static    void         pclrcurr    __P((struct process *));
  125. static    void         padd        __P((struct command *));
  126. static    int         pprint        __P((struct process *, int));
  127. static    void         ptprint    __P((struct process *));
  128. static    void         pads        __P((Char *));
  129. static    void         pkill        __P((Char **, int));
  130. static    struct process    *pgetcurr    __P((struct process *));
  131. static    void         okpcntl    __P((void));
  132.  
  133. /*
  134.  * pchild - called at interrupt level by the SIGCHLD signal
  135.  *    indicating that at least one child has terminated or stopped
  136.  *    thus at least one wait system call will definitely return a
  137.  *    childs status.  Top level routines (like pwait) must be sure
  138.  *    to mask interrupts when playing with the proclist data structures!
  139.  */
  140. sigret_t
  141. /*ARGSUSED*/
  142. pchild(snum)
  143. int snum;
  144. {
  145.     register struct process *pp;
  146.     register struct process *fp;
  147.     register int pid;
  148.     extern int insource;
  149. #ifdef BSDWAIT
  150.     union wait w;
  151. #else /* !BSDWAIT */
  152.     int     w;
  153. #endif /* !BSDWAIT */
  154.     int     jobflags;
  155. #ifdef BSDTIMES
  156.     struct rusage ru;
  157. #else /* !BSDTIMES */
  158. # ifdef _SEQUENT_
  159.     struct process_stats ru;
  160.     struct process_stats cpst1, cpst2;
  161.     timeval_t tv;
  162. # else /* !_SEQUENT_ */
  163.     struct tms proctimes;
  164.  
  165.     if (!timesdone) {
  166.     timesdone++;
  167.     (void) times(&shtimes);
  168.     }
  169. # endif    /* _SEQUENT_ */
  170. #endif /* BSDTIMES */
  171.  
  172. #ifdef JOBDEBUG
  173.     xprintf("pchild()\n");
  174. #endif    /* JOBDEBUG */
  175.  
  176. /* Christos on where the signal(SIGCHLD, pchild) shoud be:
  177.  *
  178.  * I think that it should go *after* the wait, unlike most signal handlers.
  179.  *
  180.  * In release two (for which I have manuals), it says that wait will remove
  181.  * the first child from the queue of dead children.
  182.  * All the rest of the children that die while in the signal handler of the
  183.  * SIGC(H)LD, will be placed in the queue. If signal is called to re-establish
  184.  * the signal handler, and there are items in the queue, the process will
  185.  * receive another SIGC(H)LD before signal returns. BTW this is from the
  186.  * manual page on comp-sim... Maybe it is not applicable to the hp's, but
  187.  * I read on the news in comp.unix.wizards or comp.unix.questions yesterday
  188.  * that another person was claiming the the signal() call should be after
  189.  * the wait().
  190.  */
  191.  
  192. loop:
  193.     errno = 0;            /* reset, just in case */
  194. #ifdef JOBDEBUG
  195.     xprintf("Waiting...\n");
  196.     flush();
  197. #endif
  198. #ifdef BSDJOBS
  199. # ifdef BSDTIMES
  200.     /* both a wait3 and rusage */
  201. #  if !defined(BSDWAIT) || defined(NeXT) || (defined(IRIS4D) && __STDC__)
  202.     pid = wait3(&w,
  203.        (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
  204. #  else /* BSDWAIT */
  205.     pid = wait3(&w.w_status,
  206.        (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
  207. #  endif /* BSDWAIT */
  208. # else /* !BSDTIMES */
  209. #  ifdef _SEQUENT_
  210.     (void) get_process_stats(&tv, PS_SELF, 0, &cpst1);
  211.     pid = waitpid(-1, &w,
  212.         (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
  213.     (void) get_process_stats(&tv, PS_SELF, 0, &cpst2);
  214.     pr_stat_sub(&cpst2, &cpst1, &ru);
  215. #  else    /* !_SEQUENT_ */
  216. #   ifndef POSIX
  217.     /* we have a wait3, but no rusage stuff */
  218.     pid = wait3(&w.w_status,
  219.      (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), 0);
  220. #   else /* POSIX */
  221.     pid = waitpid(-1, &w,
  222.         (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
  223. #   endif /* POSIX */
  224. #  endif /* !_SEQUENT_ */
  225. # endif    /* !BSDTIMES */
  226. #else /* !BSDJOBS */
  227. # ifdef BSDTIMES
  228. #  define HAVEwait3
  229.     /* both a wait3 and rusage */
  230. #  ifdef hpux
  231.     pid = wait3(&w.w_status, WNOHANG, 0);
  232. #  else    /* !hpux */
  233.     pid = wait3(&w.w_status, WNOHANG, &ru);
  234. #  endif /* !hpux */
  235. # else /* !BSDTIMES */
  236. # ifdef ODT  /* For Sco Unix 3.2.0 or ODT 1.0 */
  237. #  define HAVEwait3
  238.     pid = waitpid(-1, &w,
  239.         (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
  240. # endif /* ODT */        
  241. # if defined(aiws) || defined(uts)
  242. #  define HAVEwait3
  243.     pid = wait3(&w.w_status, 
  244.     (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), 0);
  245. # endif /* aiws || uts */
  246. # ifndef HAVEwait3
  247. #  ifdef UNRELSIGS
  248.     /* no wait3, therefore no rusage */
  249.     /* on Sys V, this may hang.  I hope it's not going to be a problem */
  250. #   ifdef _MINIX
  251.     pid = wait(&w);
  252. #   else /* !_MINIX */
  253.     pid = ourwait(&w.w_status);
  254. #   endif /* _MINIX */
  255. #  else    /* UNRELSIGS */
  256.     /* 
  257.      * XXX: for greater than 3 we should use waitpid(). 
  258.      * but then again, SVR4 falls into the POSIX/BSDJOBS category.
  259.      */
  260.     pid = wait(&w.w_status);
  261. #  endif /* SVID >= 3 */
  262. # endif /* HAVEwait3 */
  263. # endif    /* BSDTIMES */
  264. # ifndef BSDSIGS
  265.     (void) sigset(SIGCHLD, pchild);
  266. # endif /* !BSDSIGS */
  267. #endif /* BSDJOBS */
  268.  
  269. #ifdef JOBDEBUG
  270.     {
  271.     char    buffer[100];
  272.     xsprintf(buffer, "pid %d, retval %x termsig %x retcode %x\n",
  273.          pid, w, WTERMSIG(w), WEXITSTATUS(w));
  274.     xprintf(buffer);
  275.     flush();
  276.     }
  277. #endif /* JOBDEBUG */
  278.  
  279.     if (pid <= 0) {
  280. #ifdef JOBDEBUG
  281.     xprintf("errno == %d\n", errno);
  282. #endif
  283.     if (errno == EINTR) {
  284.         errno = 0;
  285.         goto loop;
  286.     }
  287.     pnoprocesses = pid == -1;
  288. #ifndef SIGVOID
  289.     return (0);
  290. #else /* !SIGVOID */
  291.     return;
  292. #endif /* SIGVOID */
  293.     }
  294.     for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
  295.     if (pid == pp->p_procid)
  296.         goto found;
  297. #ifndef BSDJOBS
  298.     /* this should never have happened */
  299.     stderror(ERR_SYNC, pid);
  300.     xexit(0);
  301. #else /* BSDJOBS */
  302.     goto loop;
  303. #endif /* BSDJOBS */
  304. found:
  305.     if (pid == atoi(short2str(value(STRchild))))
  306.     unsetv(STRchild);
  307.     pp->p_flags &= ~(PRUNNING | PSTOPPED | PREPORTED);
  308.     if (WIFSTOPPED(w)) {
  309.     pp->p_flags |= PSTOPPED;
  310.     pp->p_reason = WSTOPSIG(w);
  311.     }
  312.     else {
  313.     if (pp->p_flags & (PTIME | PPTIME) || adrof(STRtime))
  314. #ifndef BSDTIMES
  315. # ifdef _SEQUENT_
  316.         (void) get_process_stats(&pp->p_etime, PS_SELF, NULL, NULL);
  317. # else    /* !_SEQUENT_ */
  318.         pp->p_etime = times(&proctimes);
  319. # endif    /* !_SEQUENT_ */
  320. #else /* BSDTIMES */
  321.         (void) gettimeofday(&pp->p_etime, NULL);
  322. #endif /* BSDTIMES */
  323.  
  324.  
  325. #if defined(BSDTIMES) || defined(_SEQUENT_)
  326.     pp->p_rusage = ru;
  327. #else /* !BSDTIMES && !_SEQUENT_ */
  328.     (void) times(&proctimes);
  329.     pp->p_utime = proctimes.tms_cutime - shtimes.tms_cutime;
  330.     pp->p_stime = proctimes.tms_cstime - shtimes.tms_cstime;
  331.     shtimes = proctimes;
  332. #endif /* !BSDTIMES && !_SEQUENT_ */
  333.     if (WIFSIGNALED(w)) {
  334.         if (WTERMSIG(w) == SIGINT)
  335.         pp->p_flags |= PINTERRUPTED;
  336.         else
  337.         pp->p_flags |= PSIGNALED;
  338.         if (WCOREDUMP(w))
  339.         pp->p_flags |= PDUMPED;
  340.         pp->p_reason = WTERMSIG(w);
  341.     }
  342.     else {
  343.         pp->p_reason = WEXITSTATUS(w);
  344.         if (pp->p_reason != 0)
  345.         pp->p_flags |= PAEXITED;
  346.         else
  347.         pp->p_flags |= PNEXITED;
  348.     }
  349.     }
  350.     jobflags = 0;
  351.     fp = pp;
  352.     do {
  353.     if ((fp->p_flags & (PPTIME | PRUNNING | PSTOPPED)) == 0 &&
  354.         !child && adrof(STRtime) &&
  355. #ifdef BSDTIMES
  356.         fp->p_rusage.ru_utime.tv_sec + fp->p_rusage.ru_stime.tv_sec
  357. #else /* !BSDTIMES */
  358. # ifdef _SEQUENT_
  359.         fp->p_rusage.ps_utime.tv_sec + fp->p_rusage.ps_stime.tv_sec
  360. # else /* !_SEQUENT_ */
  361. #  ifndef POSIX
  362.         (fp->p_utime + fp->p_stime) / HZ
  363. #  else /* POSIX */
  364.         (fp->p_utime + fp->p_stime) / CLK_TCK
  365. #  endif /* POSIX */
  366. # endif /* !_SEQUENT_ */
  367. #endif /* !BSDTIMES */
  368.         >= atoi(short2str(value(STRtime))))
  369.         fp->p_flags |= PTIME;
  370.     jobflags |= fp->p_flags;
  371.     } while ((fp = fp->p_friends) != pp);
  372.     pp->p_flags &= ~PFOREGND;
  373.     if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
  374.     pp->p_flags &= ~PPTIME;
  375.     pp->p_flags |= PTIME;
  376.     }
  377.     if ((jobflags & (PRUNNING | PREPORTED)) == 0) {
  378.     fp = pp;
  379.     do {
  380.         if (fp->p_flags & PSTOPPED)
  381.         fp->p_flags |= PREPORTED;
  382.     } while ((fp = fp->p_friends) != pp);
  383.     while (fp->p_procid != fp->p_jobid)
  384.         fp = fp->p_friends;
  385.     if (jobflags & PSTOPPED) {
  386.         if (pcurrent && pcurrent != fp)
  387.         pprevious = pcurrent;
  388.         pcurrent = fp;
  389.     }
  390.     else
  391.         pclrcurr(fp);
  392.     if (jobflags & PFOREGND) {
  393.         if (jobflags & (PSIGNALED | PSTOPPED | PPTIME) ||
  394. #ifdef IIASA
  395.         jobflags & PAEXITED ||
  396. #endif /* IIASA */
  397.         !eq(dcwd->di_name, fp->p_cwd->di_name)) {
  398.         ;        /* print in pjwait */
  399.         }
  400.         /* PWP: print a newline after ^C */
  401.         else if (jobflags & PINTERRUPTED)
  402. #ifdef SHORT_STRINGS
  403.         xputchar('\r' | QUOTE), xputchar('\n');
  404. #else /* !SHORT_STRINGS */
  405.         xprintf("\215\n");    /* \215 is a quoted ^M */
  406. #endif /* !SHORT_STRINGS */
  407. #ifdef notdef
  408.         else if ((jobflags & (PTIME|PSTOPPED)) == PTIME)
  409.                 ptprint(fp);
  410. #endif
  411.     }
  412.     else {
  413.         if (jobflags & PNOTIFY || adrof(STRnotify)) {
  414. #ifdef SHORT_STRINGS
  415.         xputchar('\r' | QUOTE), xputchar('\n');
  416. #else /* !SHORT_STRINGS */
  417.         xprintf("\215\n");    /* \215 is a quoted ^M */
  418. #endif /* !SHORT_STRINGS */
  419.         (void) pprint(pp, NUMBER | NAME | REASON);
  420.         if ((jobflags & PSTOPPED) == 0)
  421.             pflush(pp);
  422.         {
  423.             extern Char GettingInput;
  424.  
  425.             if (GettingInput) {
  426.             errno = 0;
  427.             (void) Rawmode();
  428.             ClearLines();
  429.             ClearDisp();
  430.             Refresh();
  431.             }
  432.         }
  433.         }
  434.         else {
  435.         fp->p_flags |= PNEEDNOTE;
  436.         neednote++;
  437.         }
  438.     }
  439.     }
  440. #if defined(BSDJOBS) || defined(HAVEwait3)
  441.     goto loop;
  442. #endif /* BSDJOBS || HAVEwait3 */
  443. }
  444.  
  445. void
  446. pnote()
  447. {
  448.     register struct process *pp;
  449.     int     flags;
  450. #ifdef BSDSIGS
  451.     sigmask_t omask;
  452. #endif /* BSDSIGS */
  453.  
  454.     neednote = 0;
  455.     for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) {
  456.     if (pp->p_flags & PNEEDNOTE) {
  457. #ifdef BSDSIGS
  458.         omask = sigblock(sigmask(SIGCHLD));
  459. #else /* !BSDSIGS */
  460.         (void) sighold(SIGCHLD);
  461. #endif /* !BSDSIGS */
  462.         pp->p_flags &= ~PNEEDNOTE;
  463.         flags = pprint(pp, NUMBER | NAME | REASON);
  464.         if ((flags & (PRUNNING | PSTOPPED)) == 0)
  465.         pflush(pp);
  466. #ifdef BSDSIGS
  467.         (void) sigsetmask(omask);
  468. #else /* !BSDSIGS */
  469.         (void) sigrelse(SIGCHLD);
  470. #endif /* !BSDSIGS */
  471.     }
  472.     }
  473. }
  474.  
  475. /*
  476.  * pwait - wait for current job to terminate, maintaining integrity
  477.  *    of current and previous job indicators.
  478.  */
  479. void
  480. pwait()
  481. {
  482.     register struct process *fp, *pp;
  483. #ifdef BSDSIGS
  484.     sigmask_t omask;
  485. #endif /* BSDSIGS */
  486.  
  487.     /*
  488.      * Here's where dead procs get flushed.
  489.      */
  490. #ifdef BSDSIGS
  491.     omask = sigblock(sigmask(SIGCHLD));
  492. #else /* !BSDSIGS */
  493.     (void) sighold(SIGCHLD);
  494. #endif /* !BSDSIGS */
  495.     for (pp = (fp = &proclist)->p_next; pp != NULL; pp = (fp = pp)->p_next)
  496.     if (pp->p_procid == 0) {
  497.         fp->p_next = pp->p_next;
  498.         xfree((ptr_t) pp->p_command);
  499.         if (pp->p_cwd && --pp->p_cwd->di_count == 0)
  500.         if (pp->p_cwd->di_next == 0)
  501.             dfree(pp->p_cwd);
  502.         xfree((ptr_t) pp);
  503.         pp = fp;
  504.     }
  505. #ifdef BSDSIGS
  506.     (void) sigsetmask(omask);
  507. #else /* !BSDSIGS */
  508.     (void) sigrelse(SIGCHLD);
  509. # ifdef notdef
  510.     if (setintr)
  511.     sigignore(SIGINT);
  512. # endif
  513. #endif /* !BSDSIGS */
  514.     pjwait(pcurrjob);
  515. }
  516.  
  517.  
  518. /*
  519.  * pjwait - wait for a job to finish or become stopped
  520.  *    It is assumed to be in the foreground state (PFOREGND)
  521.  */
  522. void
  523. pjwait(pp)
  524.     register struct process *pp;
  525. {
  526.     register struct process *fp;
  527.     int     jobflags, reason;
  528. #ifdef BSDSIGS
  529.     sigmask_t omask;
  530. #endif /* BSDSIGS */
  531. #ifdef UNRELSIGS
  532.     sigret_t (*inthandler)();
  533. #endif /* UNRELSIGS */
  534.  
  535.     while (pp->p_procid != pp->p_jobid)
  536.     pp = pp->p_friends;
  537.     fp = pp;
  538.  
  539.     do {
  540.     if ((fp->p_flags & (PFOREGND | PRUNNING)) == PRUNNING)
  541.         xprintf("BUG: waiting for background job!\n");
  542.     } while ((fp = fp->p_friends) != pp);
  543.     /*
  544.      * Now keep pausing as long as we are not interrupted (SIGINT), and the
  545.      * target process, or any of its friends, are running
  546.      */
  547.     fp = pp;
  548. #ifdef BSDSIGS
  549.     omask = sigblock(sigmask(SIGCHLD));
  550. #endif /* BSDSIGS */
  551. #ifdef UNRELSIGS
  552.     if (setintr)
  553.         inthandler = signal(SIGINT, SIG_IGN);
  554. #endif /* UNRELSIGS */
  555.     for (;;) {
  556. #ifndef BSDSIGS
  557.     (void) sighold(SIGCHLD);
  558. #endif /* !BSDSIGS */
  559.     jobflags = 0;
  560.     do
  561.         jobflags |= fp->p_flags;
  562.     while ((fp = (fp->p_friends)) != pp);
  563.     if ((jobflags & PRUNNING) == 0)
  564.         break;
  565. #ifdef JOBDEBUG
  566.     xprintf("starting to sigpause for  SIGCHLD on %d\n", fp->p_procid);
  567. #endif /* JOBDEBUG */
  568. #ifdef BSDSIGS
  569.     /* sigpause(sigblock((sigmask_t) 0) &~ sigmask(SIGCHLD)); */
  570.     (void) sigpause(omask & ~sigmask(SIGCHLD));
  571. #else /* !BSDSIGS */
  572.     (void) sigpause(SIGCHLD);
  573. #endif /* !BSDSIGS */
  574.     }
  575. #ifdef BSDSIGS
  576.     (void) sigsetmask(omask);
  577. #else /* !BSDSIGS */
  578.     (void) sigrelse(SIGCHLD);
  579. #endif /* !BSDSIGS */
  580. #ifdef UNRELSIGS
  581.     if (setintr)
  582.         (void) signal(SIGINT, inthandler);
  583. #endif /* UNRELSIGS */
  584. #ifdef BSDJOBS
  585.     if (tpgrp > 0)        /* get tty back */
  586.     (void) tcsetpgrp(FSHTTY, tpgrp);
  587. #endif /* BSDJOBS */
  588.     if ((jobflags & (PSIGNALED | PSTOPPED | PTIME)) ||
  589.     !eq(dcwd->di_name, fp->p_cwd->di_name)) {
  590.     if (jobflags & PSTOPPED) {
  591.         xprintf("\n");
  592.         if (adrof(STRlistjobs)) {
  593.         Char   *jobcommand[3];
  594.  
  595.         jobcommand[0] = STRjobs;
  596.         if (eq(value(STRlistjobs), STRlong))
  597.             jobcommand[1] = STRml;
  598.         else
  599.             jobcommand[1] = NULL;
  600.         jobcommand[2] = NULL;
  601.  
  602.         dojobs(jobcommand, NULL);
  603.         (void) pprint(pp, SHELLDIR);
  604.         }
  605.         else
  606.         (void) pprint(pp, AREASON | SHELLDIR);
  607.     }
  608.     else
  609.         (void) pprint(pp, AREASON | SHELLDIR);
  610.     }
  611.     if ((jobflags & (PINTERRUPTED | PSTOPPED)) && setintr &&
  612.     (!gointr || !eq(gointr, STRminus))) {
  613.     if ((jobflags & PSTOPPED) == 0)
  614.         pflush(pp);
  615.     pintr1(0);
  616.     /* NOTREACHED */
  617.     }
  618.     reason = 0;
  619.     fp = pp;
  620.     do {
  621.     if (fp->p_reason)
  622.         reason = fp->p_flags & (PSIGNALED | PINTERRUPTED) ?
  623.         fp->p_reason | META : fp->p_reason;
  624.     } while ((fp = fp->p_friends) != pp);
  625.     if ((reason != 0) && (adrof(STRprintexitvalue)))    /* PWP */
  626.     xprintf("Exit %d\n", reason);
  627.     set(STRstatus, putn(reason));
  628.     if (reason && exiterr)
  629.     exitstat();
  630.     pflush(pp);
  631. }
  632.  
  633. /*
  634.  * dowait - wait for all processes to finish
  635.  */
  636.  
  637. /*ARGSUSED*/
  638. void
  639. dowait(v, c)
  640.     Char **v;
  641.     struct command *c;
  642. {
  643.     register struct process *pp;
  644. #ifdef BSDSIGS
  645.     sigmask_t omask;
  646. #endif /* BSDSIGS */
  647.  
  648.     pjobs++;
  649. #ifdef BSDSIGS
  650.     omask = sigblock(sigmask(SIGCHLD));
  651. loop:
  652. #else /* !BSDSIGS */
  653.     if (setintr)
  654.     (void) sigrelse(SIGINT);
  655. loop:
  656.     (void) sighold(SIGCHLD);
  657. #endif /* !BSDSIGS */
  658.     for (pp = proclist.p_next; pp; pp = pp->p_next)
  659.     if (pp->p_procid &&    /* pp->p_procid == pp->p_jobid && */
  660.         pp->p_flags & PRUNNING) {
  661. #ifdef BSDSIGS
  662.         (void) sigpause((sigmask_t) 0);
  663. #else /* !BSDSIGS */
  664.         (void) sigpause(SIGCHLD);
  665. #endif /* !BSDSIGS */
  666.         goto loop;
  667.     }
  668. #ifdef BSDSIGS
  669.     (void) sigsetmask(omask);
  670. #else /* !BSDSIGS */
  671.     (void) sigrelse(SIGCHLD);
  672. #endif /* !BSDSIGS */
  673.     pjobs = 0;
  674. }
  675.  
  676. /*
  677.  * pflushall - flush all jobs from list (e.g. at fork())
  678.  */
  679. static void
  680. pflushall()
  681. {
  682.     register struct process *pp;
  683.  
  684.     for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
  685.     if (pp->p_procid)
  686.         pflush(pp);
  687. }
  688.  
  689. /*
  690.  * pflush - flag all process structures in the same job as the
  691.  *    the argument process for deletion.  The actual free of the
  692.  *    space is not done here since pflush is called at interrupt level.
  693.  */
  694. static void
  695. pflush(pp)
  696.     register struct process *pp;
  697. {
  698.     register struct process *np;
  699.     register int idx;
  700.  
  701.     if (pp->p_procid == 0) {
  702.     xprintf("BUG: process flushed twice");
  703.     return;
  704.     }
  705.     while (pp->p_procid != pp->p_jobid)
  706.     pp = pp->p_friends;
  707.     pclrcurr(pp);
  708.     if (pp == pcurrjob)
  709.     pcurrjob = 0;
  710.     idx = pp->p_index;
  711.     np = pp;
  712.     do {
  713.     np->p_index = np->p_procid = 0;
  714.     np->p_flags &= ~PNEEDNOTE;
  715.     } while ((np = np->p_friends) != pp);
  716.     if (idx == pmaxindex) {
  717.     for (np = proclist.p_next, idx = 0; np; np = np->p_next)
  718.         if (np->p_index > idx)
  719.         idx = np->p_index;
  720.     pmaxindex = idx;
  721.     }
  722. }
  723.  
  724. /*
  725.  * pclrcurr - make sure the given job is not the current or previous job;
  726.  *    pp MUST be the job leader
  727.  */
  728. static void
  729. pclrcurr(pp)
  730.     register struct process *pp;
  731. {
  732.     if (pp == pcurrent)
  733.     if (pprevious != NULL) {
  734.         pcurrent = pprevious;
  735.         pprevious = pgetcurr(pp);
  736.     }
  737.     else {
  738.         pcurrent = pgetcurr(pp);
  739.         pprevious = pgetcurr(pp);
  740.     }
  741.     else if (pp == pprevious)
  742.     pprevious = pgetcurr(pp);
  743. }
  744.  
  745. /* +4 here is 1 for '\0', 1 ea for << >& >> */
  746. static Char command[PMAXLEN + 4];
  747. static int cmdlen;
  748. static Char *cmdp;
  749.  
  750. /*
  751.  * palloc - allocate a process structure and fill it up.
  752.  *    an important assumption is made that the process is running.
  753.  */
  754. void
  755. palloc(pid, t)
  756.     int     pid;
  757.     register struct command *t;
  758. {
  759.     register struct process *pp;
  760.     int     i;
  761.  
  762.     pp = (struct process *) xcalloc(1, (size_t) sizeof(struct process));
  763.     pp->p_procid = pid;
  764.     pp->p_flags = t->t_dflg & F_AMPERSAND ? PRUNNING : PRUNNING | PFOREGND;
  765.     if (t->t_dflg & F_TIME)
  766.     pp->p_flags |= PPTIME;
  767.     cmdp = command;
  768.     cmdlen = 0;
  769.     padd(t);
  770.     *cmdp++ = 0;
  771.     if (t->t_dflg & F_PIPEOUT) {
  772.     pp->p_flags |= PPOU;
  773.     if (t->t_dflg & F_STDERR)
  774.         pp->p_flags |= PDIAG;
  775.     }
  776.     pp->p_command = Strsave(command);
  777.     if (pcurrjob) {
  778.     struct process *fp;
  779.  
  780.     /* careful here with interrupt level */
  781.     pp->p_cwd = 0;
  782.     pp->p_index = pcurrjob->p_index;
  783.     pp->p_friends = pcurrjob;
  784.     pp->p_jobid = pcurrjob->p_procid;
  785.     for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends);
  786.     fp->p_friends = pp;
  787.     }
  788.     else {
  789.     pcurrjob = pp;
  790.     pp->p_jobid = pid;
  791.     pp->p_friends = pp;
  792.     pp->p_cwd = dcwd;
  793.     dcwd->di_count++;
  794.     if (pmaxindex < BIGINDEX)
  795.         pp->p_index = ++pmaxindex;
  796.     else {
  797.         struct process *np;
  798.  
  799.         for (i = 1;; i++) {
  800.         for (np = proclist.p_next; np; np = np->p_next)
  801.             if (np->p_index == i)
  802.             goto tryagain;
  803.         pp->p_index = i;
  804.         if (i > pmaxindex)
  805.             pmaxindex = i;
  806.         break;
  807.     tryagain:;
  808.         }
  809.     }
  810.     if (pcurrent == NULL)
  811.         pcurrent = pp;
  812.     else if (pprevious == NULL)
  813.         pprevious = pp;
  814.     }
  815.     pp->p_next = proclist.p_next;
  816.     proclist.p_next = pp;
  817. #ifdef BSDTIMES
  818.     (void) gettimeofday(&pp->p_btime, NULL);
  819. #else /* !BSDTIMES */
  820. # ifdef _SEQUENT_
  821.     (void) get_process_stats(&pp->p_btime, PS_SELF, NULL, NULL);
  822. # else /* !_SEQUENT_ */
  823.     {
  824.     struct tms tmptimes;
  825.  
  826.     pp->p_btime = times(&tmptimes);
  827.     }
  828. # endif /* !_SEQUENT_ */
  829. #endif /* !BSDTIMES */
  830. }
  831.  
  832. static void
  833. padd(t)
  834.     register struct command *t;
  835. {
  836.     Char  **argp;
  837.  
  838.     if (t == 0)
  839.     return;
  840.     switch (t->t_dtyp) {
  841.  
  842.     case NODE_PAREN:
  843.     pads(STRLparensp);
  844.     padd(t->t_dspr);
  845.     pads(STRspRparen);
  846.     break;
  847.  
  848.     case NODE_COMMAND:
  849.     for (argp = t->t_dcom; *argp; argp++) {
  850.         pads(*argp);
  851.         if (argp[1])
  852.         pads(STRspace);
  853.     }
  854.     break;
  855.  
  856.     case NODE_OR:
  857.     case NODE_AND:
  858.     case NODE_PIPE:
  859.     case NODE_LIST:
  860.     padd(t->t_dcar);
  861.     switch (t->t_dtyp) {
  862.     case NODE_OR:
  863.         pads(STRspor2sp);
  864.         break;
  865.     case NODE_AND:
  866.         pads(STRspand2sp);
  867.         break;
  868.     case NODE_PIPE:
  869.         pads(STRsporsp);
  870.         break;
  871.     case NODE_LIST:
  872.         pads(STRsemisp);
  873.         break;
  874.     default:
  875.         break;
  876.     }
  877.     padd(t->t_dcdr);
  878.     return;
  879.  
  880.     default:
  881.     break;
  882.     }
  883.     if ((t->t_dflg & F_PIPEIN) == 0 && t->t_dlef) {
  884.     pads((t->t_dflg & F_READ) ? STRspLarrow2sp : STRspLarrowsp);
  885.     pads(t->t_dlef);
  886.     }
  887.     if ((t->t_dflg & F_PIPEOUT) == 0 && t->t_drit) {
  888.     pads((t->t_dflg & F_APPEND) ? STRspRarrow2 : STRspRarrow);
  889.     if (t->t_dflg & F_STDERR)
  890.         pads(STRand);
  891.     pads(STRspace);
  892.     pads(t->t_drit);
  893.     }
  894. }
  895.  
  896. static void
  897. pads(cp)
  898.     Char   *cp;
  899. {
  900.     register int i;
  901.  
  902.     /*
  903.      * Avoid the Quoted Space alias hack! Reported by:
  904.      * sam@john-bigboote.ICS.UCI.EDU (Sam Horrocks)
  905.      */
  906.     if (cp[0] == STRQNULL[0])
  907.     cp++;
  908.  
  909.     i = Strlen(cp);
  910.  
  911.     if (cmdlen >= PMAXLEN)
  912.     return;
  913.     if (cmdlen + i >= PMAXLEN) {
  914.     (void) Strcpy(cmdp, STRsp3dots);
  915.     cmdlen = PMAXLEN;
  916.     cmdp += 4;
  917.     return;
  918.     }
  919.     (void) Strcpy(cmdp, cp);
  920.     cmdp += i;
  921.     cmdlen += i;
  922. }
  923.  
  924. /*
  925.  * psavejob - temporarily save the current job on a one level stack
  926.  *    so another job can be created.  Used for { } in exp6
  927.  *    and `` in globbing.
  928.  */
  929. void
  930. psavejob()
  931. {
  932.     pholdjob = pcurrjob;
  933.     pcurrjob = NULL;
  934. }
  935.  
  936. /*
  937.  * prestjob - opposite of psavejob.  This may be missed if we are interrupted
  938.  *    somewhere, but pendjob cleans up anyway.
  939.  */
  940. void
  941. prestjob()
  942. {
  943.     pcurrjob = pholdjob;
  944.     pholdjob = NULL;
  945. }
  946.  
  947. /*
  948.  * pendjob - indicate that a job (set of commands) has been completed
  949.  *    or is about to begin.
  950.  */
  951. void
  952. pendjob()
  953. {
  954.     register struct process *pp, *tp;
  955.  
  956.     if (pcurrjob && (pcurrjob->p_flags & (PFOREGND | PSTOPPED)) == 0) {
  957.     pp = pcurrjob;
  958.     while (pp->p_procid != pp->p_jobid)
  959.         pp = pp->p_friends;
  960.     xprintf("[%d]", pp->p_index);
  961.     tp = pp;
  962.     do {
  963.         xprintf(" %d", pp->p_procid);
  964.         pp = pp->p_friends;
  965.     } while (pp != tp);
  966.     xprintf("\n");
  967.     }
  968.     pholdjob = pcurrjob = 0;
  969. }
  970.  
  971. /*
  972.  * pprint - print a job
  973.  */
  974.  
  975. /*
  976.  * Hacks have been added for SVR4 to deal with pipe's being spawned in
  977.  * reverse order
  978.  *
  979.  * David Dawes (dawes@physics.su.oz.au) Oct 1991
  980.  */
  981.  
  982. static int
  983. pprint(pp, flag)
  984.     register struct process *pp;
  985.     bool    flag;
  986. {
  987.     register status, reason;
  988.     struct process *tp;
  989.     extern char *linp, linbuf[];
  990.     int     jobflags, pstatus, pcond;
  991.     char   *format;
  992.  
  993. #ifdef BACKPIPE
  994.     struct process *pipehead, *pipetail, *pmarker;
  995.     int inpipe = 0;
  996. #endif /* BACKPIPE */
  997.  
  998.     while (pp->p_procid != pp->p_jobid)
  999.     pp = pp->p_friends;
  1000.     if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
  1001.     pp->p_flags &= ~PPTIME;
  1002.     pp->p_flags |= PTIME;
  1003.     }
  1004.     tp = pp;
  1005.     status = reason = -1;
  1006.     jobflags = 0;
  1007.     do {
  1008. #ifdef BACKPIPE
  1009.     /*
  1010.      * The pipeline is reversed, so locate the real head of the pipeline
  1011.      * if pp is at the tail of a pipe (and not already in a pipeline)
  1012.      */
  1013.     if ((pp->p_friends->p_flags & PPOU) && !inpipe && (flag & NAME)) {
  1014.         inpipe = 1;
  1015.         pipetail = pp;
  1016.         do 
  1017.         pp = pp->p_friends;
  1018.         while (pp->p_friends->p_flags & PPOU);
  1019.         pipehead = pp;
  1020.         pmarker = pp;
  1021.     /*
  1022.      * pmarker is used to hold the place of the proc being processed, so
  1023.      * we can search for the next one downstream later.
  1024.      */
  1025.     }
  1026.     pcond = (tp != pp || (inpipe && tp == pp));
  1027. #else /* !BACKPIPE */
  1028.     pcond = (tp != pp);
  1029. #endif /* BACKPIPE */        
  1030.  
  1031.     jobflags |= pp->p_flags;
  1032.     pstatus = pp->p_flags & PALLSTATES;
  1033.     if (pcond && linp != linbuf && !(flag & FANCY) &&
  1034.         ((pstatus == status && pp->p_reason == reason) ||
  1035.          !(flag & REASON)))
  1036.         xprintf(" ");
  1037.     else {
  1038.         if (pcond && linp != linbuf)
  1039.         xprintf("\n");
  1040.         if (flag & NUMBER) {
  1041. #ifdef BACKPIPE
  1042.         pcond = ((pp == tp && !inpipe) ||
  1043.              (inpipe && pipetail == tp && pp == pipehead));
  1044. #else /* BACKPIPE */
  1045.         pcond = (pp == tp);
  1046. #endif /* BACKPIPE */
  1047.         if (pcond)
  1048.             xprintf("[%d]%s %c ", pp->p_index,
  1049.                 pp->p_index < 10 ? " " : "",
  1050.                 pp == pcurrent ? '+' :
  1051.                 (pp == pprevious ? '-' : ' '));
  1052.         else
  1053.             xprintf("       ");
  1054.         }
  1055.         if (flag & FANCY) {
  1056. #ifdef TCF
  1057.         extern char *sitename();
  1058.  
  1059. #endif /* TCF */
  1060.         xprintf("%5d ", pp->p_procid);
  1061. #ifdef TCF
  1062.         xprintf("%11s ", sitename(pp->p_procid));
  1063. #endif /* TCF */
  1064.         }
  1065.         if (flag & (REASON | AREASON)) {
  1066.         if (flag & NAME)
  1067. #ifdef SUSPENDED
  1068.             format = "%-23s";
  1069. #else /* !SUSPENDED */
  1070.             format = "%-21s";
  1071. #endif /* !SUSPENDED */
  1072.         else
  1073.             format = "%s";
  1074.         if (pstatus == status)
  1075.             if (pp->p_reason == reason) {
  1076.             xprintf(format, "");
  1077.             goto prcomd;
  1078.             }
  1079.             else
  1080.             reason = pp->p_reason;
  1081.         else {
  1082.             status = pstatus;
  1083.             reason = pp->p_reason;
  1084.         }
  1085.         switch (status) {
  1086.  
  1087.         case PRUNNING:
  1088.             xprintf(format, "Running ");
  1089.             break;
  1090.  
  1091.         case PINTERRUPTED:
  1092.         case PSTOPPED:
  1093.         case PSIGNALED:
  1094.             /*
  1095.              * tell what happened to the background job
  1096.              * From: Michael Schroeder 
  1097.              * <mlschroe@immd4.informatik.uni-erlangen.de>
  1098.              */
  1099.             if ((flag & REASON)
  1100.             || ((flag & AREASON)
  1101.                 && reason != SIGINT
  1102.                 && (reason != SIGPIPE
  1103.                 || (pp->p_flags & PPOU) == 0)))
  1104.             xprintf(format, mesg[pp->p_reason & ASCII].pname);
  1105.             else
  1106.             reason = -1;
  1107.             break;
  1108.  
  1109.         case PNEXITED:
  1110.         case PAEXITED:
  1111.             if (flag & REASON)
  1112.             if (pp->p_reason)
  1113. #ifdef SUSPENDED
  1114.                 xprintf("Exit %-18d", pp->p_reason);
  1115. #else /* SUSPENDED */
  1116.                 xprintf("Exit %-16d", pp->p_reason);
  1117. #endif /* SUSPENDED */
  1118.             else
  1119.                 xprintf(format, "Done");
  1120.             break;
  1121.  
  1122.         default:
  1123.             xprintf("BUG: status=%-9o", status);
  1124.         }
  1125.         }
  1126.     }
  1127. prcomd:
  1128.     if (flag & NAME) {
  1129.         xprintf("%s", short2str(pp->p_command));
  1130.         if (pp->p_flags & PPOU)
  1131.         xprintf(" |");
  1132.         if (pp->p_flags & PDIAG)
  1133.         xprintf("&");
  1134.     }
  1135.     if (flag & (REASON | AREASON) && pp->p_flags & PDUMPED)
  1136.         xprintf(" (core dumped)");
  1137.     if (tp == pp->p_friends) {
  1138.         if (flag & AMPERSAND)
  1139.         xprintf(" &");
  1140.         if (flag & JOBDIR &&
  1141.         !eq(tp->p_cwd->di_name, dcwd->di_name)) {
  1142.         xprintf(" (wd: ");
  1143.         dtildepr(value(STRhome), tp->p_cwd->di_name);
  1144.         xprintf(")");
  1145.         }
  1146.     }
  1147.     if (pp->p_flags & PPTIME && !(status & (PSTOPPED | PRUNNING))) {
  1148.         if (linp != linbuf)
  1149.         xprintf("\n\t");
  1150. #if defined(BSDTIMES) || defined(_SEQUENT_)
  1151.         prusage(&zru, &pp->p_rusage, &pp->p_etime,
  1152.             &pp->p_btime);
  1153. #else /* !BSDTIMES && !SEQUENT */
  1154.         lru.tms_utime = pp->p_utime;
  1155.         lru.tms_stime = pp->p_stime;
  1156.         lru.tms_cutime = 0;
  1157.         lru.tms_cstime = 0;
  1158.         prusage(&zru, &lru, pp->p_etime,
  1159.             pp->p_btime);
  1160. #endif /* !BSDTIMES && !SEQUENT */
  1161.  
  1162.     }
  1163. #ifdef BACKPIPE
  1164.     pcond = ((tp == pp->p_friends && !inpipe) ||
  1165.          (inpipe && pipehead->p_friends == tp && pp == pipetail));
  1166. #else  /* !BACKPIPE */
  1167.     pcond = (tp == pp->p_friends);
  1168. #endif /* BACKPIPE */
  1169.     if (pcond) {
  1170.         if (linp != linbuf)
  1171.         xprintf("\n");
  1172.         if (flag & SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) {
  1173.         xprintf("(wd now: ");
  1174.         dtildepr(value(STRhome), dcwd->di_name);
  1175.         xprintf(")\n");
  1176.         }
  1177.     }
  1178. #ifdef BACKPIPE
  1179.     if (inpipe) {
  1180.         /*
  1181.          * if pmaker == pipetail, we are finished that pipeline, and
  1182.          * can now skip to past the head
  1183.          */
  1184.         if (pmarker == pipetail) {
  1185.         inpipe = 0;
  1186.         pp = pipehead;
  1187.         }
  1188.         else {
  1189.         /*
  1190.          * set pp to one before the one we want next, so the while below
  1191.          * increments to the correct spot.
  1192.          */
  1193.         do
  1194.             pp = pp->p_friends;
  1195.             while (pp->p_friends->p_friends != pmarker);
  1196.             pmarker = pp->p_friends;
  1197.         }
  1198.     }
  1199.     pcond = ((pp = pp->p_friends) != tp || inpipe);
  1200. #else /* !BACKPIPE */
  1201.     pcond = ((pp = pp->p_friends) != tp);
  1202. #endif /* BACKPIPE */
  1203.     } while (pcond);
  1204.  
  1205.     if (jobflags & PTIME && (jobflags & (PSTOPPED | PRUNNING)) == 0) {
  1206.     if (jobflags & NUMBER)
  1207.         xprintf("       ");
  1208.     ptprint(tp);
  1209.     }
  1210.     return (jobflags);
  1211. }
  1212.  
  1213. static void
  1214. ptprint(tp)
  1215.     register struct process *tp;
  1216. {
  1217. #ifdef BSDTIMES
  1218.     struct timeval tetime, diff;
  1219.     static struct timeval ztime;
  1220.     struct rusage ru;
  1221.     static struct rusage zru;
  1222.     register struct process *pp = tp;
  1223.  
  1224.     ru = zru;
  1225.     tetime = ztime;
  1226.     do {
  1227.     ruadd(&ru, &pp->p_rusage);
  1228.     tvsub(&diff, &pp->p_etime, &pp->p_btime);
  1229.     if (timercmp(&diff, &tetime, >))
  1230.         tetime = diff;
  1231.     } while ((pp = pp->p_friends) != tp);
  1232.     prusage(&zru, &ru, &tetime, &ztime);
  1233. #else /* !BSDTIMES */
  1234. # ifdef _SEQUENT_
  1235. #  define timercmp(tvp, uvp, cmp) \
  1236.       ((tvp)->tv_sec cmp (uvp)->tv_sec || \
  1237.        (tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec)
  1238.     timeval_t tetime, diff;
  1239.     static timeval_t ztime;
  1240.     struct process_stats ru;
  1241.     static struct process_stats zru;
  1242.     register struct process *pp = tp;
  1243.  
  1244.     ru = zru;
  1245.     tetime = ztime;
  1246.     do {
  1247.     ruadd(&ru, &pp->p_rusage);
  1248.     tvsub(&diff, &pp->p_etime, &pp->p_btime);
  1249.     if (timercmp(&diff, &tetime, >))
  1250.         tetime = diff;
  1251.     } while ((pp = pp->p_friends) != tp);
  1252.     prusage(&zru, &ru, &tetime, &ztime);
  1253. # else /* !_SEQUENT_ */
  1254. #  ifndef POSIX
  1255.     static time_t ztime = 0;
  1256.     static time_t zu_time = 0;
  1257.     static time_t zs_time = 0;
  1258.     time_t  tetime, diff;
  1259.     time_t  u_time, s_time;
  1260.  
  1261. #  else    /* POSIX */
  1262.     static clock_t ztime = 0;
  1263.     static clock_t zu_time = 0;
  1264.     static clock_t zs_time = 0;
  1265.     clock_t tetime, diff;
  1266.     clock_t u_time, s_time;
  1267.  
  1268. #  endif /* POSIX */
  1269.     struct tms zts, rts;
  1270.     register struct process *pp = tp;
  1271.  
  1272.     u_time = zu_time;
  1273.     s_time = zs_time;
  1274.     tetime = ztime;
  1275.     do {
  1276.     u_time += pp->p_utime;
  1277.     s_time += pp->p_stime;
  1278.     diff = pp->p_etime - pp->p_btime;
  1279.     if (diff > tetime)
  1280.         tetime = diff;
  1281.     } while ((pp = pp->p_friends) != tp);
  1282.     zts.tms_utime = zu_time;
  1283.     zts.tms_stime = zs_time;
  1284.     zts.tms_cutime = 0;
  1285.     zts.tms_cstime = 0;
  1286.     rts.tms_utime = u_time;
  1287.     rts.tms_stime = s_time;
  1288.     rts.tms_cutime = 0;
  1289.     rts.tms_cstime = 0;
  1290.     prusage(&zts, &rts, tetime, ztime);
  1291. # endif /* !_SEQUENT_ */
  1292. #endif    /* !BSDTIMES */
  1293. }
  1294.  
  1295. /*
  1296.  * dojobs - print all jobs
  1297.  */
  1298. /*ARGSUSED*/
  1299. void
  1300. dojobs(v, c)
  1301.     Char  **v;
  1302.     struct command *c;
  1303. {
  1304.     register struct process *pp;
  1305.     register int flag = NUMBER | NAME | REASON;
  1306.     int     i;
  1307.  
  1308.     if (chkstop)
  1309.     chkstop = 2;
  1310.     if (*++v) {
  1311.     if (v[1] || !eq(*v, STRml))
  1312.         stderror(ERR_JOBS);
  1313.     flag |= FANCY | JOBDIR;
  1314.     }
  1315.     for (i = 1; i <= pmaxindex; i++)
  1316.     for (pp = proclist.p_next; pp; pp = pp->p_next)
  1317.         if (pp->p_index == i && pp->p_procid == pp->p_jobid) {
  1318.         pp->p_flags &= ~PNEEDNOTE;
  1319.         if (!(pprint(pp, flag) & (PRUNNING | PSTOPPED)))
  1320.             pflush(pp);
  1321.         break;
  1322.         }
  1323. }
  1324.  
  1325. /*
  1326.  * dofg - builtin - put the job into the foreground
  1327.  */
  1328. /*ARGSUSED*/
  1329. void
  1330. dofg(v, c)
  1331.     Char  **v;
  1332.     struct command *c;
  1333. {
  1334.     register struct process *pp;
  1335.  
  1336.     okpcntl();
  1337.     ++v;
  1338.     do {
  1339.     pp = pfind(*v);
  1340.     pstart(pp, 1);
  1341. #ifndef BSDSIGS
  1342. # ifdef notdef
  1343.     if (setintr)
  1344.         sigignore(SIGINT);
  1345. # endif
  1346. #endif /* !BSDSIGS */
  1347.     pjwait(pp);
  1348.     } while (*v && *++v);
  1349. }
  1350.  
  1351. /*
  1352.  * %... - builtin - put the job into the foreground
  1353.  */
  1354. /*ARGSUSED*/
  1355. void
  1356. dofg1(v, c)
  1357.     Char  **v;
  1358.     struct command *c;
  1359. {
  1360.     register struct process *pp;
  1361.  
  1362.     okpcntl();
  1363.     pp = pfind(v[0]);
  1364.     pstart(pp, 1);
  1365. #ifndef BSDSIGS
  1366. # ifdef notdef
  1367.     if (setintr)
  1368.     sigignore(SIGINT);
  1369. # endif
  1370. #endif /* !BSDSIGS */
  1371.     pjwait(pp);
  1372. }
  1373.  
  1374. /*
  1375.  * dobg - builtin - put the job into the background
  1376.  */
  1377. /*ARGSUSED*/
  1378. void
  1379. dobg(v, c)
  1380.     Char  **v;
  1381.     struct command *c;
  1382. {
  1383.     register struct process *pp;
  1384.  
  1385.     okpcntl();
  1386.     ++v;
  1387.     do {
  1388.     pp = pfind(*v);
  1389.     pstart(pp, 0);
  1390.     } while (*v && *++v);
  1391. }
  1392.  
  1393. /*
  1394.  * %... & - builtin - put the job into the background
  1395.  */
  1396. /*ARGSUSED*/
  1397. void
  1398. dobg1(v, c)
  1399.     Char  **v;
  1400.     struct command *c;
  1401. {
  1402.     register struct process *pp;
  1403.  
  1404.     pp = pfind(v[0]);
  1405.     pstart(pp, 0);
  1406. }
  1407.  
  1408. /*
  1409.  * dostop - builtin - stop the job
  1410.  */
  1411. /*ARGSUSED*/
  1412. void
  1413. dostop(v, c)
  1414.     Char  **v;
  1415.     struct command *c;
  1416. {
  1417. #ifdef BSDJOBS
  1418.     pkill(++v, SIGSTOP);
  1419. #endif /* BSDJOBS */
  1420. }
  1421.  
  1422. /*
  1423.  * dokill - builtin - superset of kill (1)
  1424.  */
  1425. /*ARGSUSED*/
  1426. void
  1427. dokill(v, c)
  1428.     Char  **v;
  1429.     struct command *c;
  1430. {
  1431.     register int signum, len = 0;
  1432.     register char *name;
  1433.     extern int T_Cols;
  1434.  
  1435.     v++;
  1436.     if (v[0] && v[0][0] == '-') {
  1437.     if (v[0][1] == 'l') {
  1438.         for (signum = 1; signum <= NSIG; signum++) {
  1439.         if ((name = mesg[signum].iname) != NULL) {
  1440.             len += strlen(name) + 1;
  1441.             if (len >= T_Cols - 1) {
  1442.             xprintf("\n");
  1443.             len = strlen(name) + 1;
  1444.             }
  1445.             xprintf("%s ", name);
  1446.         }
  1447.         }
  1448.         xprintf("\n");
  1449.         return;
  1450.     }
  1451.     if (Isdigit(v[0][1])) {
  1452.         signum = atoi(short2str(v[0] + 1));
  1453.         if (signum < 0 || signum > NSIG)
  1454.         stderror(ERR_NAME | ERR_BADSIG);
  1455.     }
  1456.     else {
  1457.         for (signum = 1; signum <= NSIG; signum++)
  1458.         if (mesg[signum].iname &&
  1459.             eq(&v[0][1], str2short(mesg[signum].iname)))
  1460.             goto gotsig;
  1461.         setname(short2str(&v[0][1]));
  1462.         stderror(ERR_NAME | ERR_UNKSIG);
  1463.     }
  1464. gotsig:
  1465.     v++;
  1466.     }
  1467.     else
  1468.     signum = SIGTERM;
  1469.     pkill(v, signum);
  1470. }
  1471.  
  1472. static void
  1473. pkill(v, signum)
  1474.     Char  **v;
  1475.     int     signum;
  1476. {
  1477.     register struct process *pp, *np;
  1478.     int jobflags = 0, err1 = 0;
  1479.     pid_t     pid;
  1480. #ifdef BSDSIGS
  1481.     sigmask_t omask;
  1482. #endif /* BSDSIGS */
  1483.     Char   *cp;
  1484.  
  1485. #ifdef BSDSIGS
  1486.     omask = sigmask(SIGCHLD);
  1487.     if (setintr)
  1488.     omask |= sigmask(SIGINT);
  1489.     omask = sigblock(omask) & ~omask;
  1490. #else /* !BSDSIGS */
  1491.     if (setintr)
  1492.     (void) sighold(SIGINT);
  1493.     (void) sighold(SIGCHLD);
  1494. #endif /* !BSDSIGS */
  1495.     gflag = 0, tglob(v);
  1496.     if (gflag) {
  1497.     v = globall(v);
  1498.     if (v == 0)
  1499.         stderror(ERR_NAME | ERR_NOMATCH);
  1500.     }
  1501.     else {
  1502.     v = gargv = saveblk(v);
  1503.     trim(v);
  1504.     }
  1505.  
  1506.     while (v && (cp = *v)) {
  1507.     if (*cp == '%') {
  1508.         np = pp = pfind(cp);
  1509.         do
  1510.         jobflags |= np->p_flags;
  1511.         while ((np = np->p_friends) != pp);
  1512. #ifdef BSDJOBS
  1513.         switch (signum) {
  1514.  
  1515.         case SIGSTOP:
  1516.         case SIGTSTP:
  1517.         case SIGTTIN:
  1518.         case SIGTTOU:
  1519.         if ((jobflags & PRUNNING) == 0) {
  1520. # ifdef SUSPENDED
  1521.             xprintf("%s: Already suspended\n",
  1522.                 short2str(cp));
  1523. # else /* !SUSPENDED */
  1524.             xprintf("%s: Already stopped\n",
  1525.                 short2str(cp));
  1526. # endif /* !SUSPENDED */
  1527.             err1++;
  1528.             goto cont;
  1529.         }
  1530.         break;
  1531.         /*
  1532.          * suspend a process, kill -CONT %, then type jobs; the shell
  1533.          * says it is suspended, but it is running; thanks jaap..
  1534.          */
  1535.         case SIGCONT:
  1536.         pstart(pp, 0);
  1537.         goto cont;
  1538.         default:
  1539.         break;
  1540.         }
  1541. #endif /* BSDJOBS */
  1542.         if (killpg(pp->p_jobid, signum) < 0) {
  1543.         xprintf("%s: %s\n", short2str(cp), strerror(errno));
  1544.         err1++;
  1545.         }
  1546. #ifdef BSDJOBS
  1547.         if (signum == SIGTERM || signum == SIGHUP)
  1548.         (void) killpg(pp->p_jobid, SIGCONT);
  1549. #endif /* BSDJOBS */
  1550.     }
  1551.     else if (!(Isdigit(*cp) || *cp == '-'))
  1552.         stderror(ERR_NAME | ERR_JOBARGS);
  1553.     else {
  1554.         pid = atoi(short2str(cp));
  1555.         if (kill(pid, signum) < 0) {
  1556.         xprintf("%d: %s\n", pid, strerror(errno));
  1557.         err1++;
  1558.         goto cont;
  1559.         }
  1560. #ifdef BSDJOBS
  1561.         if (signum == SIGTERM || signum == SIGHUP)
  1562.         (void) kill(pid, SIGCONT);
  1563. #endif /* BSDJOBS */
  1564.     }
  1565. cont:
  1566.     v++;
  1567.     }
  1568.     if (gargv)
  1569.     blkfree(gargv), gargv = 0;
  1570. #ifdef BSDSIGS
  1571.     (void) sigsetmask(omask);
  1572. #else /* !BSDSIGS */
  1573.     (void) sigrelse(SIGCHLD);
  1574.     if (setintr)
  1575.     (void) sigrelse(SIGINT);
  1576. #endif /* !BSDSIGS */
  1577.     if (err1)
  1578.     stderror(ERR_SILENT);
  1579. }
  1580.  
  1581. /*
  1582.  * pstart - start the job in foreground/background
  1583.  */
  1584. void
  1585. pstart(pp, foregnd)
  1586.     register struct process *pp;
  1587.     int     foregnd;
  1588. {
  1589.     register struct process *np;
  1590. #ifdef BSDSIGS
  1591.     sigmask_t omask;
  1592. #endif /* BSDSIGS */
  1593.     long    jobflags = 0;
  1594.  
  1595. #ifdef BSDSIGS
  1596.     omask = sigblock(sigmask(SIGCHLD));
  1597. #else /* !BSDSIGS */
  1598.     (void) sighold(SIGCHLD);
  1599. #endif
  1600.     np = pp;
  1601.     do {
  1602.     jobflags |= np->p_flags;
  1603.     if (np->p_flags & (PRUNNING | PSTOPPED)) {
  1604.         np->p_flags |= PRUNNING;
  1605.         np->p_flags &= ~PSTOPPED;
  1606.         if (foregnd)
  1607.         np->p_flags |= PFOREGND;
  1608.         else
  1609.         np->p_flags &= ~PFOREGND;
  1610.     }
  1611.     } while ((np = np->p_friends) != pp);
  1612.     if (!foregnd)
  1613.     pclrcurr(pp);
  1614.     (void) pprint(pp, foregnd ? NAME | JOBDIR : NUMBER | NAME | AMPERSAND);
  1615. #ifdef BSDJOBS
  1616.     if (foregnd)
  1617.     (void) tcsetpgrp(FSHTTY, pp->p_jobid);
  1618.     if (jobflags & PSTOPPED)
  1619.     (void) killpg(pp->p_jobid, SIGCONT);
  1620. #endif /* BSDJOBS */
  1621. #ifdef BSDSIGS
  1622.     (void) sigsetmask(omask);
  1623. #else /* !BSDSIGS */
  1624.     (void) sigrelse(SIGCHLD);
  1625. #endif /* !BSDSIGS */
  1626. }
  1627.  
  1628. void
  1629. panystop(neednl)
  1630.     bool    neednl;
  1631. {
  1632.     register struct process *pp;
  1633.  
  1634.     chkstop = 2;
  1635.     for (pp = proclist.p_next; pp; pp = pp->p_next)
  1636.     if (pp->p_flags & PSTOPPED)
  1637.         stderror(ERR_STOPPED, neednl ? "\n" : "");
  1638. }
  1639.  
  1640. struct process *
  1641. pfind(cp)
  1642.     Char   *cp;
  1643. {
  1644.     register struct process *pp, *np;
  1645.  
  1646.     if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2) || eq(cp, STRcentplus)) {
  1647.     if (pcurrent == NULL)
  1648.         stderror(ERR_NAME | ERR_JOBCUR);
  1649.     return (pcurrent);
  1650.     }
  1651.     if (eq(cp, STRcentminus) || eq(cp, STRcenthash)) {
  1652.     if (pprevious == NULL)
  1653.         stderror(ERR_NAME | ERR_JOBPREV);
  1654.     return (pprevious);
  1655.     }
  1656.     if (Isdigit(cp[1])) {
  1657.     int     idx = atoi(short2str(cp + 1));
  1658.  
  1659.     for (pp = proclist.p_next; pp; pp = pp->p_next)
  1660.         if (pp->p_index == idx && pp->p_procid == pp->p_jobid)
  1661.         return (pp);
  1662.     stderror(ERR_NAME | ERR_NOSUCHJOB);
  1663.     }
  1664.     np = NULL;
  1665.     for (pp = proclist.p_next; pp; pp = pp->p_next)
  1666.     if (pp->p_procid == pp->p_jobid) {
  1667.         if (cp[1] == '?') {
  1668.         register Char *dp;
  1669.  
  1670.         for (dp = pp->p_command; *dp; dp++) {
  1671.             if (*dp != cp[2])
  1672.             continue;
  1673.             if (prefix(cp + 2, dp))
  1674.             goto match;
  1675.         }
  1676.         }
  1677.         else if (prefix(cp + 1, pp->p_command)) {
  1678.     match:
  1679.         if (np)
  1680.             stderror(ERR_NAME | ERR_AMBIG);
  1681.         np = pp;
  1682.         }
  1683.     }
  1684.     if (np)
  1685.     return (np);
  1686.     stderror(ERR_NAME | cp[1] == '?' ? ERR_JOBPAT : ERR_NOSUCHJOB);
  1687.     /* NOTREACHED */
  1688.     return (0);
  1689. }
  1690.  
  1691.  
  1692. /*
  1693.  * pgetcurr - find most recent job that is not pp, preferably stopped
  1694.  */
  1695. static struct process *
  1696. pgetcurr(pp)
  1697.     register struct process *pp;
  1698. {
  1699.     register struct process *np;
  1700.     register struct process *xp = NULL;
  1701.  
  1702.     for (np = proclist.p_next; np; np = np->p_next)
  1703.     if (np != pcurrent && np != pp && np->p_procid &&
  1704.         np->p_procid == np->p_jobid) {
  1705.         if (np->p_flags & PSTOPPED)
  1706.         return (np);
  1707.         if (xp == NULL)
  1708.         xp = np;
  1709.     }
  1710.     return (xp);
  1711. }
  1712.  
  1713. /*
  1714.  * donotify - flag the job so as to report termination asynchronously
  1715.  */
  1716. /*ARGSUSED*/
  1717. void
  1718. donotify(v, c)
  1719.     Char  **v;
  1720.     struct command *c;
  1721. {
  1722.     register struct process *pp;
  1723.  
  1724.     pp = pfind(*++v);
  1725.     pp->p_flags |= PNOTIFY;
  1726. }
  1727.  
  1728. /*
  1729.  * Do the fork and whatever should be done in the child side that
  1730.  * should not be done if we are not forking at all (like for simple builtin's)
  1731.  * Also do everything that needs any signals fiddled with in the parent side
  1732.  *
  1733.  * Wanttty tells whether process and/or tty pgrps are to be manipulated:
  1734.  *    -1:    leave tty alone; inherit pgrp from parent
  1735.  *     0:    already have tty; manipulate process pgrps only
  1736.  *     1:    want to claim tty; manipulate process and tty pgrps
  1737.  * It is usually just the value of tpgrp.
  1738.  */
  1739.  
  1740. int
  1741. pfork(t, wanttty)
  1742.     struct command *t;        /* command we are forking for */
  1743.     int     wanttty;
  1744. {
  1745.     register int pid;
  1746.     bool    ignint = 0;
  1747.     int     pgrp;
  1748. #ifdef BSDSIGS
  1749.     sigmask_t omask;
  1750. #endif /* BSDSIGS */
  1751. #ifdef SIGSYNCH
  1752.     sigvec_t osv;
  1753.     static sigvec_t nsv = {synch_handler, ~0, 0};
  1754. #endif /* SIGSYNCH */
  1755.  
  1756.     /*
  1757.      * A child will be uninterruptible only under very special conditions.
  1758.      * Remember that the semantics of '&' is implemented by disconnecting the
  1759.      * process from the tty so signals do not need to ignored just for '&'.
  1760.      * Thus signals are set to default action for children unless: we have had
  1761.      * an "onintr -" (then specifically ignored) we are not playing with
  1762.      * signals (inherit action)
  1763.      */
  1764.     if (setintr)
  1765.     ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT))
  1766.         || (gointr && eq(gointr, STRminus));
  1767.     /*
  1768.      * Check for maximum nesting of 16 processes to avoid Forking loops
  1769.      */
  1770.     if (child == 16)
  1771.     stderror(ERR_NESTING, 16);
  1772.     /*
  1773.      * Hold SIGCHLD until we have the process installed in our table.
  1774.      */
  1775. #ifdef SIGSYNCH
  1776.     if (mysigvec(SIGSYNCH, &nsv, &osv))
  1777.     stderror(ERR_SYSTEM, "pfork: sigvec set", strerror(errno));
  1778. #endif /* SIGSYNCH */
  1779. #ifdef BSDSIGS
  1780.     omask = sigblock(sigmask(SIGCHLD));
  1781. #else /* !BSDSIGS */
  1782.     (void) sighold(SIGCHLD);
  1783. #endif /* !BSDSIGS */
  1784.     while ((pid = fork()) < 0)
  1785.     if (setintr == 0)
  1786.         (void) sleep(FORKSLEEP);
  1787.     else {
  1788. #ifdef BSDSIGS
  1789.         (void) sigsetmask(omask);
  1790. #else /* !BSDSIGS */
  1791.         (void) sigrelse(SIGINT);
  1792.         (void) sigrelse(SIGCHLD);
  1793. #endif /* !BSDSIGS */
  1794.         stderror(ERR_NOPROC);
  1795.     }
  1796.     if (pid == 0) {
  1797.     settimes();
  1798.     pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
  1799.     pflushall();
  1800.     pcurrjob = NULL;
  1801. #if !defined(BSDTIMES) && !defined(_SEQUENT_) 
  1802.     timesdone = 0;
  1803. #endif /* !defined(BSDTIMES) && !defined(_SEQUENT_) */
  1804.     child++;
  1805.     if (setintr) {
  1806.         setintr = 0;    /* until I think otherwise */
  1807. #ifndef BSDSIGS
  1808.         (void) sigrelse(SIGCHLD);
  1809. #endif /* !BSDSIGS */
  1810.         /*
  1811.          * Children just get blown away on SIGINT, SIGQUIT unless "onintr
  1812.          * -" seen.
  1813.          */
  1814.         (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL);
  1815.         (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
  1816. #ifdef BSDJOBS
  1817.         if (wanttty >= 0) {
  1818.         /* make stoppable */
  1819.         (void) signal(SIGTSTP, SIG_DFL);
  1820.         (void) signal(SIGTTIN, SIG_DFL);
  1821.         (void) signal(SIGTTOU, SIG_DFL);
  1822.         }
  1823. #endif /* BSDJOBS */
  1824.         (void) signal(SIGTERM, parterm);
  1825.     }
  1826.     else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) {
  1827.         (void) signal(SIGINT, SIG_IGN);
  1828.         (void) signal(SIGQUIT, SIG_IGN);
  1829.     }
  1830. #ifdef OREO
  1831.     sigignore(SIGIO);    /* ignore SIGIO in child too */
  1832. #endif /* OREO */
  1833.  
  1834.     pgetty(wanttty, pgrp);
  1835.     /*
  1836.      * Nohup and nice apply only to NODE_COMMAND's but it would be nice
  1837.      * (?!?) if you could say "nohup (foo;bar)" Then the parser would have
  1838.      * to know about nice/nohup/time
  1839.      */
  1840.     if (t->t_dflg & F_NOHUP)
  1841.         (void) signal(SIGHUP, SIG_IGN);
  1842.     if (t->t_dflg & F_NICE)
  1843. #ifdef BSDNICE
  1844.         (void) setpriority(PRIO_PROCESS, 0, t->t_nice);
  1845. #else /* !BSDNICE */
  1846.         (void) nice(t->t_nice);
  1847. #endif /* !BSDNICE */
  1848. #ifdef F_VER
  1849.         if (t->t_dflg & F_VER) {
  1850.         Setenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53);
  1851.         dohash(NULL, NULL);
  1852.     }
  1853. #endif /* F_VER */
  1854. #ifdef SIGSYNCH
  1855.     /* rfw 8/89 now parent can continue */
  1856.     if (kill(getppid(), SIGSYNCH))
  1857.         stderror(ERR_SYSTEM, "pfork child: kill", strerror(errno));
  1858. #endif /* SIGSYNCH */
  1859.  
  1860.     }
  1861.     else {
  1862. #ifdef POSIXJOBS
  1863.     if (wanttty >= 0)
  1864.         (void) setpgid(pid, pcurrjob ? pcurrjob->p_jobid : pid);
  1865. #endif /* POSIXJOBS */
  1866.     palloc(pid, t);
  1867. #ifdef SIGSYNCH
  1868.     /*
  1869.      * rfw 8/89 Wait for child to own terminal.  Solves half of ugly
  1870.      * synchronization problem.  With this change, we know that the only
  1871.      * reason setpgrp to a previous process in a pipeline can fail is that
  1872.      * the previous process has already exited. Without this hack, he may
  1873.      * either have exited or not yet started to run.  Two uglies become
  1874.      * one.
  1875.      */
  1876.     sigpause(omask & ~SYNCHMASK);
  1877.     if (mysigvec(SIGSYNCH, &osv, NULL))
  1878.         stderror(ERR_SYSTEM, "pfork parent: sigvec restore",
  1879.              strerror(errno));
  1880. #endif /* SIGSYNCH */
  1881.  
  1882. #ifdef BSDSIGS
  1883.     (void) sigsetmask(omask);
  1884. #else /* !BSDSIGS */
  1885.     (void) sigrelse(SIGCHLD);
  1886. #endif /* !BSDSIGS */
  1887.     }
  1888.     return (pid);
  1889. }
  1890.  
  1891. static void
  1892. okpcntl()
  1893. {
  1894.     if (tpgrp == -1)
  1895.     stderror(ERR_JOBCONTROL);
  1896.     if (tpgrp == 0)
  1897.     stderror(ERR_JOBCTRLSUB);
  1898. }
  1899.  
  1900. /*
  1901.  * if we don't have vfork(), things can still go in the wrong order
  1902.  * resulting in the famous 'Stopped (tty output)'. But some systems
  1903.  * don't permit the setpgid() call, (these are more recent secure
  1904.  * systems such as ibm's aix), when they do. Then we'd rather print 
  1905.  * an error message than hang the shell!
  1906.  * I am open to suggestions how to fix that.
  1907.  */
  1908. void
  1909. pgetty(wanttty, pgrp)
  1910.     int     wanttty, pgrp;
  1911. {
  1912. #ifdef BSDJOBS
  1913. # if defined(BSDSIGS) && defined(POSIXJOBS)
  1914.     sigmask_t omask = 0;
  1915. # endif /* BSDSIGS && POSIXJOBS */
  1916.  
  1917. # ifdef JOBDEBUG
  1918.     xprintf("wanttty %d\n", wanttty);
  1919. # endif
  1920.  
  1921. # ifdef POSIXJOBS
  1922.     /*
  1923.      * christos: I am blocking the tty signals till I've set things
  1924.      * correctly....
  1925.      */
  1926.     if (wanttty > 0)
  1927. #  ifdef BSDSIGS
  1928.     omask = sigblock(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU));
  1929. #  else /* !BSDSIGS */
  1930.     {
  1931.     (void) sighold(SIGTSTP);
  1932.     (void) sighold(SIGTTIN);
  1933.     (void) sighold(SIGTTOU);
  1934.     }
  1935. #  endif /* !BSDSIGS */
  1936. # endif /* POSIXJOBS */
  1937.  
  1938. # ifndef POSIXJOBS
  1939.     if (wanttty > 0)
  1940.     (void) tcsetpgrp(FSHTTY, pgrp);
  1941. # endif /* !POSIXJOBS */
  1942.  
  1943.     /*
  1944.      * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
  1945.      * Don't check for tpgrp >= 0 so even non-interactive shells give
  1946.      * background jobs process groups Same for the comparison in the other part
  1947.      * of the #ifdef
  1948.      */
  1949.     if (wanttty >= 0)
  1950.     if (setpgid(0, pgrp) == -1) {
  1951. # ifdef BACKPIPE
  1952.         /*
  1953.               * This usually happens in svr4 when the last command in a pipe
  1954.          * either couldn't be started, or exits without waiting for input.
  1955.          * Putting in the xexit() hangs the shell, so leave it out.
  1956.          * (DHD)
  1957.               */
  1958. #  ifdef JOBDEBUG
  1959.         xprintf("tcsh: setpgid error (%s).\n", strerror(errno));
  1960.         xprintf("pgrp = %d, shell pid = %d\n",pgrp,getpid());
  1961. #  endif /* JOBDEBUG */
  1962. # else /* !BACKPIPE */
  1963. #  if !defined(ISC) && !defined(SCO) && !defined(cray)
  1964.         /* XXX: Wrong but why? */
  1965.         xprintf("tcsh: setpgid error (%s).\n", strerror(errno));
  1966. #  endif /* !ISC && !SCO && !cray */
  1967.         xexit(0);
  1968. # endif /* BACKPIPE */
  1969.     }
  1970.  
  1971. # ifdef POSIXJOBS
  1972.     if (wanttty > 0) {
  1973.     (void) tcsetpgrp(FSHTTY, pgrp);
  1974. #  ifdef BSDSIGS
  1975.     (void) sigsetmask(omask);
  1976. #  else /* BSDSIGS */
  1977.     (void) sigrelse(SIGTSTP);
  1978.     (void) sigrelse(SIGTTIN);
  1979.     (void) sigrelse(SIGTTOU);
  1980. #  endif /* !BSDSIGS */
  1981.     }
  1982. # endif /* POSIXJOBS */
  1983.  
  1984.     if (tpgrp > 0)
  1985.     tpgrp = 0;        /* gave tty away */
  1986. #endif /* BSDJOBS */
  1987. }
  1988.